﻿using System;
using System.Collections.Generic;
using System.Windows;
using GalaSoft.MvvmLight.Messaging;
using mal.WP7.GoogleAnalytics.Business.GoogleApi;

namespace mal.WP7.GoogleAnalytics.Business.Repository
{
    public class Website
    {
        #region Fields
        private const string DashboardDayKeyFormat = "DashboardDayKey-{0}";
        private const string DayKeyFormat = "DayKey-{0}";
        private const string DashboardWeekKeyFormat = "DashboardWeekKey-{0}";
        private const string WeeksKeyFormat = "WeeksKey-{0}";
        private const string DashboardMonthKeyFormat = "DashboardMonthKey-{0}";
        private const string MonthsKeyFormat = "MonthsKey-{0}";
        private const string DashboardYearKeyFormat = "DashboardYearKey-{0}";

        private IGoogleAnalyticsService googleAnalyticsService;

        private string name;
        private string id;

        private List<Statistic> dashboardDay;
        private bool isDashboardDayLoading = false;

        private List<Statistic> days;
        private bool isDayLoading = false;

        private List<Statistic> dashboardWeek;
        private bool isDashboardWeekLoading = false;

        private List<Statistic> weeks;
        private bool isWeeksLoading = false;

        private List<Statistic> dashboardMonth;
        private bool isDashboardMonthLoading = false;

        private List<Statistic> months;
        private bool isMonthsLoading = false;

        private List<Statistic> dashboardYear;
        private bool isDashboardYearLoading = false;
        #endregion

        #region Construction / Destruction
        public Website()
        {
        }
        #endregion

        #region enum, struct, class

        #endregion

        #region Properties
        public string Name
        {
            get
            {
                return this.name;
            }

            set
            {
                if (this.name != value)
                {
                    this.name = value;
                }
            }
        }

        public string Id
        {
            get
            {
                return this.id;
            }

            set
            {
                if (this.id != value)
                {
                    this.id = value;
                }
            }
        }        

        public List<Statistic> DashboardDay
        {
            get
            {
                if (this.dashboardDay == null)
                {
                    this.dashboardDay = CachedObjectManager.GetCachedObject<List<Statistic>>(this.DashboardDayKey);
                    if (this.dashboardDay == null)
                    {
                        this.LoadFeedDashboardDayAsync();
                    }
                }

                return this.dashboardDay;
            }
        }

        public List<Statistic> Days
        {
            get
            {
                if (this.days == null)
                {
                    this.days = CachedObjectManager.GetCachedObject<List<Statistic>>(this.DayKey);
                    if (this.days == null)
                    {
                        this.LoadFeedDaysAsync();
                    }
                }

                return this.days;
            }
        }

        public List<Statistic> DashboardWeek
        {
            get
            {
                if (this.dashboardWeek == null)
                {
                    this.dashboardWeek = CachedObjectManager.GetCachedObject<List<Statistic>>(this.DashboardWeekKey);
                    if (this.dashboardWeek == null)
                    {
                        this.LoadFeedDashboardWeekAsync();
                    }
                }

                return this.dashboardWeek;
            }
        }

        public double DashboardWeekCurrentValue
        {
            get
            {
                if (this.dashboardWeek != null && this.DashboardWeek.Count >= 1)
                {
                    return this.DashboardWeek[this.DashboardWeek.Count - 1].Value;
                }

                return 0;
            }
        }

        public double DashboardWeekPreviousValue
        {
            get
            {
                if (this.dashboardWeek != null && this.DashboardWeek.Count >=2)
                {
                    Statistic currentWeek = this.DashboardWeek[this.DashboardWeek.Count - 1];
                    Statistic previousWeek = this.DashboardWeek[this.DashboardWeek.Count - 2];

                    double currentValue= currentWeek.Value;
                    double previousValue= previousWeek.Value;

                    double weekElapsedDay = (int)(DateTime.Now.AddDays(-1)).DayOfWeek + 1;

                    previousValue = previousValue * weekElapsedDay / 7.0;

                    return previousValue;
                }

                return 0;
            }
        }

        public List<Statistic> Weeks
        {
            get
            {
                if (this.weeks == null)
                {
                    this.weeks = CachedObjectManager.GetCachedObject<List<Statistic>>(this.WeeksKey);
                    if (this.weeks == null)
                    {
                        this.LoadFeedWeeskAsync();
                    }
                }

                return this.weeks;
            }
        }

        public List<Statistic> DashboardMonth
        {
            get
            {
                if (this.dashboardMonth == null)
                {
                    this.dashboardMonth = CachedObjectManager.GetCachedObject<List<Statistic>>(this.DashboardMonthKey);
                    if (this.dashboardMonth == null)
                    {
                        this.LoadFeedDashboardMonthAsync();
                    }
                }

                return this.dashboardMonth;
            }
        }

        public List<Statistic> Months
        {
            get
            {
                if (this.months == null)
                {
                    this.months = CachedObjectManager.GetCachedObject<List<Statistic>>(this.MonthsKey);
                    if (this.months == null)
                    {
                        this.LoadFeedMonthsAsync();
                    }
                }

                return this.months;
            }
        }

        public List<Statistic> DashboardYear
        {
            get
            {
                if (this.dashboardYear == null)
                {
                    this.dashboardYear = CachedObjectManager.GetCachedObject<List<Statistic>>(this.DashboardYearKey);
                    if (this.dashboardYear == null)
                    {
                        this.LoadFeedDashboardYearAsync();
                    }
                }

                return this.dashboardYear;
            }
        }

        public IGoogleAnalyticsService GoogleAnalyticsService
        {
            get
            {
                return this.googleAnalyticsService;
            }

            set
            {
                this.googleAnalyticsService = value;
                this.googleAnalyticsService.GetFeedCompleted += new GetFeedCompletedEventHandler(this.OnGetFeedCompleted);
            }
        }

        private string DashboardDayKey
        {
            get
            {
                return string.Format(DashboardDayKeyFormat, this.id);
            }
        }

        private string DayKey
        {
            get
            {
                return string.Format(DayKeyFormat, this.id);
            }
        }

        private string DashboardWeekKey
        {
            get
            {
                return string.Format(DashboardWeekKeyFormat, this.id);
            }
        }

        private string WeeksKey
        {
            get
            {
                return string.Format(WeeksKeyFormat, this.id);
            }
        }

        private string DashboardMonthKey
        {
            get
            {
                return string.Format(DashboardMonthKeyFormat, this.id);
            }
        }

        private string MonthsKey
        {
            get
            {
                return string.Format(MonthsKeyFormat, this.id);
            }
        }

        private string DashboardYearKey
        {
            get
            {
                return string.Format(DashboardYearKeyFormat, this.id);
            }
        }
        #endregion

        #region Methods
        private void LoadFeedDashboardDayAsync()
        {
            if (this.dashboardDay == null && !this.isDashboardDayLoading)
            {
                this.isDashboardDayLoading = true;
                this.googleAnalyticsService.GetFeedDashboardDayAsync(this);
            }
        }

        private void LoadFeedDaysAsync()
        {
            if (this.days == null && !this.isDayLoading)
            {
                this.isDayLoading = true;
                this.googleAnalyticsService.GetFeedDaysAsync(this);
            }
        }

        private void LoadFeedDashboardWeekAsync()
        {
            if (this.dashboardWeek == null && !this.isDashboardWeekLoading)
            {
                this.isDashboardWeekLoading = true;
                this.googleAnalyticsService.GetFeedDashboardWeekAsync(this);
            }
        }

        private void LoadFeedWeeskAsync()
        {
            if (this.weeks == null && !this.isWeeksLoading)
            {
                this.isWeeksLoading = true;
                this.googleAnalyticsService.GetFeedWeeksAsync(this);
            }
        }

        private void LoadFeedDashboardMonthAsync()
        {
            if (this.dashboardMonth == null && !this.isDashboardMonthLoading)
            {
                this.isDashboardMonthLoading = true;
                this.googleAnalyticsService.GetFeedDashboardMonthAsync(this);
            }
        }

        private void LoadFeedMonthsAsync()
        {
            if (this.months == null && !this.isMonthsLoading)
            {
                this.isMonthsLoading = true;
                this.googleAnalyticsService.GetFeedMonthsAsync(this);
            }
        }

        private void LoadFeedDashboardYearAsync()
        {
            if (this.dashboardYear == null && !this.isDashboardYearLoading)
            {
                this.isDashboardYearLoading = true;
                this.googleAnalyticsService.GetFeedDashboardYearAsync(this);
            }
        }

        private void SendWebsiteStatisticsAvailableMessage(WebsiteStatisticsAvailableMessage message)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                Messenger.Default.Send<WebsiteStatisticsAvailableMessage>(message);
            });
        }
        #endregion

        #region Events
        private void OnGetFeedCompleted(object sender, GetFeedCompletedEventArgs e)
        {
            bool saveDashboardDay = false;
            bool saveDay = false;
            bool saveDashboardWeek = false;
            bool saveWeeks = false;
            bool saveDashboardMonth = false;
            bool saveMonths = false;
            bool saveDashboardYear = false;

            if (e.WebsiteId == this.Id)
            {  
                if (e.Error != null)
                {
                    this.SendWebsiteStatisticsAvailableMessage(new WebsiteStatisticsAvailableMessage(this, e.Error));
                }
                else
                {
                    foreach (Statistic stat in e.Statistics)
                    {
                        switch (stat.Dimension)
                        {
                            case Dimension.Day:
                                if (e.Statistics.Count == 2)
                                {
                                    if (this.dashboardDay == null)
                                    {
                                        this.dashboardDay = new List<Statistic>();
                                    }

                                    this.dashboardDay.Add(stat);
                                    saveDashboardDay = true;
                                    this.isDashboardDayLoading = false;
                                }
                                else
                                {
                                    if (this.days == null)
                                    {
                                        this.days = new List<Statistic>();
                                    }

                                    this.days.Add(stat);
                                    saveDay = true;
                                    this.isDayLoading = false;
                                }

                                break;

                            case Dimension.Week:
                                if (e.Statistics.Count == 2)
                                {
                                    if (this.dashboardWeek == null)
                                    {
                                        this.dashboardWeek = new List<Statistic>();
                                    }

                                    this.dashboardWeek.Add(stat);
                                    saveDashboardWeek = true;
                                    this.isDashboardWeekLoading = false;
                                }
                                else
                                {
                                    if (this.weeks == null)
                                    {
                                        this.weeks = new List<Statistic>();
                                    }

                                    this.weeks.Add(stat);
                                    saveWeeks = true;
                                    this.isWeeksLoading = false;
                                }

                                break;

                            case Dimension.Month:
                                if (e.Statistics.Count == 2)
                                {
                                    if (this.dashboardMonth == null)
                                    {
                                        this.dashboardMonth = new List<Statistic>();
                                    }

                                    this.dashboardMonth.Add(stat);
                                    saveDashboardMonth = true;
                                    this.isDashboardMonthLoading = false;
                                }
                                else
                                {
                                    if (this.months == null)
                                    {
                                        this.months = new List<Statistic>();
                                    }

                                    this.months.Add(stat);
                                    saveMonths = true;
                                    this.isMonthsLoading = false;
                                }

                                break;

                            case Dimension.Year:
                                if (this.dashboardYear == null)
                                {
                                    this.dashboardYear = new List<Statistic>();
                                }

                                this.dashboardYear.Add(stat);
                                saveDashboardYear = true;
                                this.isDashboardYearLoading = false;

                                break;
                        }
                    }

                    WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.Unknown;

                    if (saveDashboardDay)
                    {
                        CachedObjectManager.InsertCachedObject<List<Statistic>>(this.dashboardDay, this.DashboardDayKey);
                        statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.DashboardDay;
                    }

                    if (saveDay)
                    {
                        CachedObjectManager.InsertCachedObject<List<Statistic>>(this.days, this.DayKey);
                        statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.Day;
                    }

                    if (saveDashboardWeek)
                    {
                        CachedObjectManager.InsertCachedObject<List<Statistic>>(this.dashboardWeek, this.DashboardWeekKey);
                        statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.DashboardWeek;
                    }

                    if (saveWeeks)
                    {
                        CachedObjectManager.InsertCachedObject<List<Statistic>>(this.weeks, this.WeeksKey);
                        statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.Week;
                    }

                    if (saveDashboardMonth)
                    {
                        CachedObjectManager.InsertCachedObject<List<Statistic>>(this.dashboardMonth, this.DashboardMonthKey);
                        statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.DashboardMonth;
                    }

                    if (saveMonths)
                    {
                        CachedObjectManager.InsertCachedObject<List<Statistic>>(this.months, this.MonthsKey);
                        statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.Month;
                    }

                    if (saveDashboardYear)
                    {
                        CachedObjectManager.InsertCachedObject<List<Statistic>>(this.dashboardYear, this.DashboardYearKey);
                        statisticsType = WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType.DashboardYear;
                    }

                    this.SendWebsiteStatisticsAvailableMessage(new WebsiteStatisticsAvailableMessage(this, statisticsType));
                }
            }
        }
        #endregion
    }
}
